package com.mall.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.category.spi.model.Category;
import com.category.spi.model.CategoryTreeDTO;
import com.category.spi.service.CategoryService;
import com.mall.api.dao.CategoryMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryMapper categoryMapper;

    @Override
    public Long create(Category category) {
        //基础校验
        if(!StringUtils.hasText(category.getName())) {
            throw new IllegalArgumentException("name 不能为空");
        }
        if (!StringUtils.hasText(category.getSlug())) {
            throw new IllegalArgumentException("slug 不能为空");
        }
        if(category.getStatus() == null) {
            category.setStatus(1);
        }
        if(category.getIsLeaf() == null) {
            category.setIsLeaf(1);
        }
        if(category.getSortOrder() == null) {
            category.setSortOrder(0);
        }

        //顶级还是子级
        if(category.getParentId() == null ) {
            //顶级 先insert拿到id 再设置path
            category.setLevel(1);
            categoryMapper.insert(category);
            category.setPath("/" + category.getId());
            categoryMapper.updateById(category);
            return category.getId();
        } else {
            // 子级：检查父节点 按照父节点计算level/path
            Category parent = categoryMapper.selectById(category.getParentId());
            if(parent == null || parent.getDeletedAt() != null) {
                throw new IllegalArgumentException("父节点不存在或者被删除");
            }
            int parentLevel = (parent.getLevel() == null ? 1 : parent.getLevel());
            category.setLevel(parentLevel + 1);
            categoryMapper.insert(category);
            String parentPath = StringUtils.hasText(parent.getPath()) ? parent.getPath() : ("/" + parent.getId());
            category.setPath(parentPath + "/" + category.getId());
            categoryMapper.updateById(category);
            //父节点不再是叶子
            if(parent.getIsLeaf() !=null && parent.getIsLeaf() == 1) {
                Category patch = new Category();
                patch.setId(parent.getId());
                patch.setIsLeaf(0);
                categoryMapper.updateById(patch);
            }
            return category.getId();
        }
    }

    @Override
    public boolean updateById(Category category) {
       if(category.getId() == null) {
           throw new IllegalArgumentException("id不能为空");
       }
       return categoryMapper.updateById(category) > 0;
    }

    @Override
    public Category getById(Long id) {
       Category c = categoryMapper.selectById(id);
       if(c == null) {
           return  null;
       }
       return c.getCreatedAt() == null ? c : null;
    }

    @Override
    public List<Category> pageQuery(String keyword, Long parentId, Integer level, Integer status, int page, int size) {
        //分页保护
        int safePage = page < 1 ? 1 : page;
        int safeSize = size < 1 || size > 100 ? 10 : size;
        int offset = (safePage - 1) * safeSize;


        //条件
        LambdaQueryWrapper<Category> qw = new LambdaQueryWrapper<>();
        qw.eq(parentId != null,Category::getParentId,parentId);
        qw.eq(level != null,Category::getLevel,level);
        qw.eq(status != null, Category::getStatus, status);
        if (StringUtils.hasText(keyword)) {
            qw.and(w -> w.like(Category::getName, keyword)
                    .or().like(Category::getSlug, keyword));
        }
        qw.isNull(Category::getDeletedAt);
        qw.orderByAsc(Category::getSortOrder).orderByAsc(Category::getId);
        qw.last("LIMIT " + safeSize + " OFFSET " + offset);

        return categoryMapper.selectList(qw);
    }

    @Override
    public long count(String keyword, Long parentId, Integer level, Integer status) {
        LambdaQueryWrapper<Category> qw = new LambdaQueryWrapper<>();
        qw.eq(parentId != null, Category::getParentId, parentId);
        qw.eq(level != null, Category::getLevel, level);
        qw.eq(status != null, Category::getStatus, status);
        if (StringUtils.hasText(keyword)) {
            qw.and(w -> w.like(Category::getName, keyword)
                    .or().like(Category::getSlug, keyword));
        }
        qw.isNull(Category::getDeletedAt);
        return categoryMapper.selectCount(qw);
    }

    @Override
    public List<Category> listChildren(Long parentId, Integer status) {
        LambdaQueryWrapper<Category> qw = new LambdaQueryWrapper<>();
        qw.eq(parentId == null, Category::getParentId, null); // 顶级
        qw.eq(parentId != null, Category::getParentId, parentId);
        qw.eq(status != null, Category::getStatus, status);
        qw.isNull(Category::getDeletedAt);
        qw.orderByAsc(Category::getSortOrder).orderByAsc(Category::getId);
        return categoryMapper.selectList(qw);
    }

    @Override
    public List<CategoryTreeDTO> tree(Integer status) {
       //全量读取有效分类
        LambdaQueryWrapper<Category> qw = new LambdaQueryWrapper<>();
        qw.eq(status != null,Category::getStatus,status);
        qw.isNull(Category::getDeletedAt);
        qw.orderByAsc(Category::getSortOrder).orderByAsc(Category::getId);
        List<Category> all = categoryMapper.selectList(qw);
        if(all.isEmpty()) return Collections.emptyList();

        //转换为dto
        List<CategoryTreeDTO> allDTOs = all.stream().map(this::convertToDTO).collect(Collectors.toList());

        //构建父子关系映射
        Map<Long,List<CategoryTreeDTO>> parentToChildren = allDTOs.stream().filter(dto -> dto.getParentId() != null).collect(Collectors.groupingBy(CategoryTreeDTO::getParentId));

        //设置children
        allDTOs.forEach(dto -> {
            List<CategoryTreeDTO> children = parentToChildren.get(dto.getId());
            dto.setChildren(children != null ? children : Collections.emptyList());
        });

        //返回顶级节点
        return allDTOs.stream().filter(dto -> dto.getParentId() == null).collect(Collectors.toList());

    }

    private CategoryTreeDTO convertToDTO(Category category) {
        CategoryTreeDTO dto = new CategoryTreeDTO();
        BeanUtils.copyProperties(category, dto);
        
        return dto;
    }

    @Override
    public boolean move(Long id, Long newParentId) {
       Category node = categoryMapper.selectById(id);
       if(node == null || node.getDeletedAt() != null) {
           throw  new IllegalArgumentException("该分类已被删除");
       }
       Category parent = null;
       String newPath;
       int newLevel;

        if (newParentId == null) {
            // 置顶级
            newLevel = 1;
            newPath = "/" + id;
        } else {
            parent = categoryMapper.selectById(newParentId);
            if (parent == null || parent.getDeletedAt() != null) {
                throw new IllegalArgumentException("新父分类不存在或已删除");
            }
            // 防环路：新父的 path 不能以当前节点 path 为前缀
            String selfPath = StringUtils.hasText(node.getPath()) ? node.getPath() : ("/" + id);
            String parentPath = StringUtils.hasText(parent.getPath()) ? parent.getPath() : ("/" + parent.getId());
            if (parentPath.equals(selfPath) || parentPath.startsWith(selfPath + "/")) {
                throw new IllegalArgumentException("不允许将分类移动到自身或其子孙节点下");
            }
            int parentLevel = (parent.getLevel() == null ? 1 : parent.getLevel());
            newLevel = parentLevel + 1;
            newPath = parentPath + "/" + id;
        }

        // 更新节点
        Category patch = new Category();
        patch.setId(id);
        patch.setParentId(newParentId);
        patch.setLevel(newLevel);
        patch.setPath(newPath);
        boolean ok = categoryMapper.updateById(patch) > 0;

        if (ok) {
            // 旧父若无子节点，置为叶子
            if (node.getParentId() != null) {
                LambdaQueryWrapper<Category> q1 = new LambdaQueryWrapper<>();
                q1.eq(Category::getParentId, node.getParentId());
                q1.isNull(Category::getDeletedAt);
                long cnt = categoryMapper.selectCount(q1);
                if (cnt == 0) {
                    Category p = new Category();
                    p.setId(node.getParentId());
                    p.setIsLeaf(1);
                    categoryMapper.updateById(p);
                }
            }
            // 新父必为非叶子
            if (newParentId != null) {
                Category p = new Category();
                p.setId(newParentId);
                p.setIsLeaf(0);
                categoryMapper.updateById(p);
            }
        }
        return ok;
    }


    @Override
    public boolean softDelete(Long id){
        // 默认：存在子分类则禁止删除
        LambdaQueryWrapper<Category> qw = new LambdaQueryWrapper<>();
        qw.eq(Category::getParentId, id);
        qw.isNull(Category::getDeletedAt);
        if (categoryMapper.selectCount(qw) > 0) {
            throw new IllegalArgumentException("存在子分类，禁止删除（请先处理子分类）");
        }
        Category patch = new Category();
        patch.setId(id);
        patch.setDeletedAt(LocalDateTime.now());
        boolean ok = categoryMapper.updateById(patch) > 0;

        // 若父节点因删除子节点而无子节点，则置为叶子
        if (ok) {
            Category node = categoryMapper.selectById(id);
            if (node != null && node.getParentId() != null) {
                LambdaQueryWrapper<Category> q2 = new LambdaQueryWrapper<>();
                q2.eq(Category::getParentId, node.getParentId());
                q2.isNull(Category::getDeletedAt);
                if (categoryMapper.selectCount(q2) == 0) {
                    Category p = new Category();
                    p.setId(node.getParentId());
                    p.setIsLeaf(1);
                    categoryMapper.updateById(p);
                }
            }
        }
        return ok;
    }
}
